/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gui;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import matching.triple.ClassTriple;
import matching.triple.DataPropertyTriple;
import matching.triple.ObjectPropertyTriple;
import ontology.Ontology;
import org.semanticweb.owl.model.OWLClass;
import org.semanticweb.owl.model.OWLDataProperty;
import org.semanticweb.owl.model.OWLDescription;
import org.semanticweb.owl.model.OWLObjectProperty;
import uk.ac.manchester.cs.owl.OWLClassImpl;

/**
 *
 * @author livia
 */
public class OntologyTree {
    private JTree tree;
    private Ontology onto;
    private DefaultMutableTreeNode root;
    private DefaultMutableTreeNode selectedNode;
    protected MatchingViewManager.TripleViewManager tripleViewer;
    
    public OntologyTree(Ontology onto) {        
        this.onto = onto;
        this.root = new DefaultMutableTreeNode("Ontology"+onto.owl.getURI());      
        DefaultMutableTreeNode node;
        
        // inclui as classes
        for (OWLClass cl : onto.owl.getReferencedClasses()) {
            // caso a classe nao seja subclasse de alguma outra
            if(cl.getSuperClasses(onto.owl).isEmpty()){
                LinkedList<String> classes = new LinkedList<String>();
                classes.addAll(onto.getClassesName());
                node =  loadClass(cl, classes);
                if(node != null)root.add(node);
            }
        }
        this.tree = new JTree(root);
        declareEvents();
    }

    private void declareEvents(){
        tree.addMouseListener(new MouseAdapter() {
           @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2 &&  SwingUtilities.isRightMouseButton(e)){
                    //pega o elemento selecionado
                    TreePath selectedPath = tree.getSelectionPath();
                    selectedNode = (DefaultMutableTreeNode) selectedPath.getLastPathComponent();
                    //manda gerenciador trata a seleção
                    if(!(selectedNode.getUserObject() instanceof String)){
                       sendTriple();
                    }
                    else selectedNode = null;
                }
            }
        });
    }

    private void sendTriple(){
        tripleViewer.clear();
        if(selectedNode.getUserObject() instanceof OWLClassImpl){
            tripleViewer.loadTripleViewer(getTripleClass((OWLClass)(selectedNode.getUserObject())));
        }else{
            DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();
            if (parent.getUserObject().equals("DataProperties")){
                tripleViewer.loadTripleViewer(getDataPropertyTriple(((ArrayList<Object>)selectedNode.getUserObject()).get(0).toString(), ((DefaultMutableTreeNode)parent.getParent()).getUserObject().toString()));
            }
            else if (parent.getUserObject().equals("ObjectProperties")){
                tripleViewer.loadTripleViewer(getObjectPropertyTriple(((ArrayList<Object>)selectedNode.getUserObject()).get(0).toString(),((DefaultMutableTreeNode)parent.getParent()).getUserObject().toString()));
            }
        }

    }

    private DefaultMutableTreeNode loadClass(OWLClass cl, LinkedList<String> classes){
        DefaultMutableTreeNode dtNode;
        DefaultMutableTreeNode node;
        DefaultMutableTreeNode objNode;
        DefaultMutableTreeNode clNode = null;
        if(classes.contains(cl.toString())){           
            classes.remove(cl.toString());
            clNode = new DefaultMutableTreeNode(cl);
            dtNode = new DefaultMutableTreeNode("DataProperties");
            objNode = new DefaultMutableTreeNode("ObjectProperties");
            
            for (OWLDescription subcl : cl.getSubClasses(onto.owl)) {
                node = loadClass(subcl.asOWLClass(), classes);
                if(node != null )clNode.add(node);
            }

            ArrayList<Object> content;

            if(!onto.getDataPropertiesOf(cl.toString()).isEmpty()){
                clNode.add(dtNode);
                for (OWLDataProperty dt : onto.getDataPropertiesOf(cl.toString())) {
                   content = new ArrayList<Object>();
                   content.add(dt);
                   content.addAll(dt.getRanges(onto.owl));
                   dtNode.add(new DefaultMutableTreeNode(content));
                }
            }
            if(!onto.getObjPropertiesOf(cl.toString()).isEmpty()){
                clNode.add(objNode);
                for (OWLObjectProperty ob : onto.getObjPropertiesOf(cl.toString())) {
                   content = new ArrayList<Object>();
                   content.add(ob);
                   content.addAll(ob.getRanges(onto.owl));
                   objNode.add(new DefaultMutableTreeNode(content));
                }
            }
           
       }
       return clNode;
    }

    

    // carrega a ontologia em uma jscroll pane
    public JTree getTree(){
        return  tree;
    }

    private ClassTriple getTripleClass(OWLClass cls) {
        return new ClassTriple(cls, null, onto);
    }

    private DataPropertyTriple getDataPropertyTriple(String dataProp, String cls) {
       // System.out.println(onto.getClass(cls));
        return new DataPropertyTriple(onto.getDataProperty(dataProp), onto.getClass(cls), null, onto);
    }

    private ObjectPropertyTriple getObjectPropertyTriple(String objProp, String cls) {
       // System.out.println(onto.getClass(cls));
       return new ObjectPropertyTriple(onto.getObjectProperty(objProp), onto.getClass(cls), null, onto);
    }
              
}
